//###############
//FILE : SimpleFileDatabase.java
//WRITER : Daniel Lowengrub, daniel_i_l, 320687098
//EXERCISE : oop ex3 2011
//DESCRIPTION:
//See below
//###############
package oop.ex3.filemanager;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;


/**
 * This implements a FileDatabase by storing a concurrent hash map of filen names and
 * file statuses. This implementation supports multiple threads adding and removing files at the same
 * time and openening streams concurrently. The methods that check the number of streams and streaming
 * permission will always return the most up-to-date value.
 * @author daniel
 */
public class SimpleFileDatabase implements FileDatabase{
    private File _sourceDirectory;
    private ConcurrentHashMap<String, FileStatus> _fileInformation;
    
    public SimpleFileDatabase(String sourceDirectory) {
        _sourceDirectory = new File(sourceDirectory);
        _fileInformation = new ConcurrentHashMap<String, FileStatus>();
        
        File[] files = _sourceDirectory.listFiles();
        for (int i=0; i<files.length; ++i) {
            FileStatus status = new FileStatus();
            _fileInformation.put(files[i].getName(), status);
        }
    }
            
    public ArrayList<String> getFileNames() {
        ArrayList<String> output = new ArrayList<String>();
        for (String fileName : _fileInformation.keySet())
            output.add(fileName);
        
        return output;
    }
    
    public ArrayList<String> getSortedFileNames() {
        ArrayList<String> output = getFileNames();
        Collections.sort(output);
        return output;
    }
    public boolean hasFile(String fileName) {
        return _fileInformation.containsKey(fileName);
    }

    public boolean removeFile(String fileName) {
        _fileInformation.remove(fileName);
         File removedFile = getFileFromName(fileName);
         return removedFile.delete();
    }

    public boolean renameFile(String oldName, String newName) {
        File oldFile = getFileFromName(oldName);
        File newFile = getFileFromName(newName);

        if (!oldFile.renameTo(newFile))
            return false;

        //move the information as well
        FileStatus info = _fileInformation.get(oldName);
        _fileInformation.put(newName, info);
        _fileInformation.remove(oldName);

        return true;
    }

    private File getFileFromName(String fileName) {
        return new File(_sourceDirectory, fileName);
    }

    public FileOutputStream createNewFile(String fileName) {
        FileStatus status = new FileStatus();
        status.setCreationStatus(false); //the file hasn't been finished yet.
        _fileInformation.put(fileName, status);

        File newFile = getFileFromName(fileName);
        try {
            newFile.createNewFile();
        } catch (IOException ex) {
            ex.printStackTrace();
            //we assume access to the directory
        }

        FileOutputStream newStream = null;
        try {
            newStream = new FileOutputStream(newFile);
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
            //we just created the file so we know it exists
        }

        return newStream;
    }

    public FileInputStream getFileStream(String fileName) {
        File file = getFileFromName(fileName);
        FileInputStream inputStream = null;

        try {
            inputStream = new FileInputStream(file);
        } catch (IOException ex) {
            ex.printStackTrace();
            //we assume access to the directory
        }

        return inputStream;
    }

    public long getFileLength(String fileName) {
        File file = getFileFromName(fileName);
        return file.length();
    }

    public boolean currentlyStreaming(String fileName) {
        return _fileInformation.get(fileName).getNumberOfStreams() > 0;
    }

    public int getNumberOfStreams(String fileName) {
    	return _fileInformation.get(fileName).getNumberOfStreams();
    }
    public boolean streamingPermission(String fileName) {
        return _fileInformation.get(fileName).getStreamingPermission();
    }

    public void setStreamingPermission(String fileName, boolean permission) {
        FileStatus fileInfo = _fileInformation.get(fileName);
        fileInfo.setStreamingPermission(permission);
    }

    public boolean finishedCreation(String fileName) {
        return _fileInformation.get(fileName).finishedCreation();
    }

    public void addStream(String fileName) {
        _fileInformation.get(fileName).addStream();
    }

    public void removeStream(String fileName) {
        _fileInformation.get(fileName).removeStream();
    }

    public void setCreationStatus(String fileName, boolean status) {
        _fileInformation.get(fileName).setCreationStatus(status);
    }

}
